/**
 * 
 */
package edu.byu.nlp.pipes;

import java.util.Iterator;
import java.util.List;

import com.google.common.base.Function;
import com.google.common.collect.Lists;

/**
 * @author robbie
 *
 */
public class SerialPipeFactoryBuilder<IL, ID, OL, OD> {

	private List<PipeFactory> pipes = Lists.newArrayList();
	
	public <L, D> SerialPipeFactoryBuilder<IL, ID, L, D> add(PipeFactory<OL, OD, L, D> p) {
		pipes.add(p);
		return (SerialPipeFactoryBuilder<IL, ID, L, D>) this;
	}
	
	public <TD> SerialPipeFactoryBuilder<IL, ID, OL, TD> addDataTransform(Function<? super OD, TD> f) {
		pipes.add(PipeFactories.<OL, OD, TD>dataTransformingPipeFactory(f));
		return (SerialPipeFactoryBuilder<IL, ID, OL, TD>) this;
	}

	public <TL> SerialPipeFactoryBuilder<IL, ID, TL, OD> addLabelTransform(Function<? super OL, TL> f) {
		pipes.add(PipeFactories.<OL, OD, TL>labelTransformingPipeFactory(f));
		return (SerialPipeFactoryBuilder<IL, ID, TL, OD>) this;
	}
	
	public PipeFactory<IL, ID, OL, OD> build() {
		return new PipeFactory<IL, ID, OL, OD>() {

			@Override
			public PipeAndData<IL, ID, OL, OD> process(Iterable<Instance<IL, ID>> input) {
				Iterator<PipeFactory> it = pipes.iterator();
				List<Pipe> pipes = Lists.newArrayList();
				Iterable toProcess = input;
				while (it.hasNext()) {
					PipeAndData pad = it.next().process(toProcess);
					pipes.add(pad.getPipe());
					toProcess = pad.getOutput();
				}
				
				return PipeAndData.from(toProcess, new SerialPipe(pipes));
			}

		};
	}
}
